package sg.edu.nus.iss.phoenix.users.service;

import java.sql.SQLException;
import java.util.List;

import sg.edu.nus.iss.phoenix.presenterproducer.dao.PresenterDAO;
import sg.edu.nus.iss.phoenix.users.dao.UserRoleDAO;
import sg.edu.nus.iss.phoenix.authenticate.dao.RoleDao;
import sg.edu.nus.iss.phoenix.authenticate.dao.UserDao;
import sg.edu.nus.iss.phoenix.authenticate.entity.Role;
import sg.edu.nus.iss.phoenix.authenticate.entity.User;
import sg.edu.nus.iss.phoenix.core.exceptions.NotFoundException;
import sg.edu.nus.iss.phoenix.dao.DAOFactory;

/**
 * Maintain User Service. This class contains all maintain users service methods
 * 
 * @author Puwanendran Nishanthan
 */
public class MaintainUsersService {
	DAOFactory factory;
	UserDao udao;
	RoleDao rdao;
	PresenterDAO presenterdao;
	
	/**
	 * Constructor method for {@link MaintainUsersService}
	 */
	public MaintainUsersService(){
		super();
		factory = new DAOFactory();
		udao = factory.getUserDAO();
		rdao = factory.getRoleDAO();
		presenterdao = factory.getPresenterDAO();
	}
	
	/**
	 * Method to reset the password of the {@link User} to the new password specified in the {@link User} object
	 * @param user
	 * 		the {@link User} who's password is required to be reset
	 * @return {@link User}
	 * 		the {@link User} who's password is required to be reset
	 */
	public User resetPassword(User user){
		
		try {
			udao.setPassword(user);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return user;
	}
	
	/**
	 * Method to find a {@link User} with a specific username
	 * @param user
	 * 		{@link User} containing the username to search for
	 * @return {@link User}
	 * 		{@link User}
	 */
	public User findUser(User user){
		try {
			return udao.getObject(user.getName());
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (NotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * Method to create a new {@link User}
	 * @param user
	 * 		{@link User} to be created
	 */
	public void createUser(User user){
		try {
			udao.create(user);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Method to update a {@link User}
	 * @param user
	 * 		{@link User} to be updated
	 */
	public void updateUser(User user){
		try {
			udao.save(user);
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (NotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * Method to delete a {@link User}
	 * @param user
	 * 		{@link User} to be deleted
	 * @throws Exception
	 */
	public void deleteUser(User user) throws Exception{
		try {
			if (presenterdao.isPresenterWithFutureSchedule(user.getId())){
				throw new Exception("The user have schedules for future. cannot be deletd.");
			}
			udao.delete(user);
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (NotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * Get the {@link Role} from the specified roleId
	 * @param roleId
	 * 			id of the role to find
	 * @return {@link User}
	 * 		{@link Role}
	 */
	public Role findRole(long roleId){
		try {
			return rdao.getObject(roleId);
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (NotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * Method to remove {@link Role} assigned to the specified userID
	 * @param userID
	 * 		Id of user whose {@link Role} is to be removed
	 */
	public void deleteUserRoles(long userID){
		try {
			 rdao.deleteUserRoles(userID);
		} catch (SQLException e) {
			e.printStackTrace();
		}

	}
	
	/**
	 * Method to return a list of {@link Role} with the specified roleId
	 * @param roleId
	 * @return list of {@link Role}
	 */
	public List<Role> searchUserRoles(long roleId){
		try {
			return rdao.searchUserRoles(roleId);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * Method to grant access to a particular user
	 * @param uservalueObject {@link User} the user to grant access to  
	 * @param rolevalueObject {@link Role} granted to the user
	 * @param currentUser {@link User} granting the access
	 */
	public  void grantAccess(User uservalueObject, Role rolevalueObject, User currentUser) 
	{
		try {
			 rdao.grantAccess(uservalueObject, rolevalueObject, currentUser);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

}
